// 主进程 - TabManager.ts
import {BrowserWindow, WebContentsView} from 'electron';
import { logger, LogCategory } from '../logger';

// 标签页数据接口
export interface TabInfo {
  id: number;
  url: string;
  title: string;
  favicon?: string;
  isLoading: boolean;
  canGoBack: boolean;
  canGoForward: boolean;
  hasError?: boolean;
  errorDescription?: string;
  isHibernated?: boolean;
  resumeURL?: string;
  isolationGroup?: number; // 隔离分组ID
  privateMode?: boolean; // 无痕模式标志
}

export class TabManager {
  private tabs: WebContentsView[] = [];
  private tabInfos: Map<number, TabInfo> = new Map();
  // 新增: 从WebContentsID到TabID的映射
  private webContentsToTabId: Map<number, number> = new Map();
  // 新增: 从索引到TabID的映射
  private indexToTabId: Map<number, number> = new Map();
  
  private currentTabIndex = -1;
  private window: BrowserWindow;
  private nextTabId = 0;
  // 存储会话分区映射关系，键为分组ID，值为会话分区名称
  private sessionPartitions: Map<number, string> = new Map();
  // 默认分组ID
  private readonly DEFAULT_ISOLATION_GROUP = 0;

  constructor(win: BrowserWindow) {
    this.window = win;
    this.setupResizeHandler();
    // 初始化默认分组的会话分区 - 移除窗口ID，只使用分组标识
    this.sessionPartitions.set(this.DEFAULT_ISOLATION_GROUP, `persist:default-group`);
    logger.info('TabManager', LogCategory.WINDOW, `TabManager初始化完成，窗口ID: ${win.id}`);
  }

  private setupResizeHandler() {
    this.window.on('resize', () => {
      this.updateAllViewBounds();
    });
  }

  // 更新所有标签页的大小
  private updateAllViewBounds() {
    this.tabs.forEach(view => this.updateViewBounds(view));
  }

  // 生成新的标签页ID
  private generateTabId(): number {
    return this.nextTabId++;
  }

  // 获取会话分区名称
  private getSessionPartition(isolationGroup?: number, isPrivate: boolean = false): string {
    // 如果是无痕模式，则返回临时会话
    if (isPrivate) {
      return `${Date.now()}-private`;
    }

    // 使用提供的分组ID或默认分组
    const groupId = isolationGroup ?? this.DEFAULT_ISOLATION_GROUP;

    // 检查是否已存在此分组的会话分区
    if (!this.sessionPartitions.has(groupId)) {
      // 创建新的分区名称并存储 - 移除窗口ID，只使用分组ID，使不同窗口的相同分组共享数据
      const partitionName = `persist:group-${groupId}`;
      this.sessionPartitions.set(groupId, partitionName);
    }

    return this.sessionPartitions.get(groupId)!;
  }

  createTab(url: string, isolationGroup?: number, isPrivate: boolean = false): number {
    // 获取会话分区名称
    const partition = this.getSessionPartition(isolationGroup, isPrivate);

    // 创建新的 WebContentsView 实例
    const view = new WebContentsView({
      webPreferences: {
        sandbox: true,
        contextIsolation: true,
        partition: partition, // 使用会话分区实现数据隔离或共享
        // 增强安全设置
        nodeIntegration: false,
        webSecurity: true,
        allowRunningInsecureContent: false,
        images: true,
        javascript: true,
        plugins: false,
        webgl: true,
        enableWebSQL: false
      }
    });

    const tabId = this.generateTabId();
    const newIndex = this.tabs.length;

    // 初始化标签信息
    this.tabInfos.set(tabId, {
      id: tabId,
      url: url,
      title: '新标签页',
      isLoading: true,
      canGoBack: false,
      canGoForward: false,
      isolationGroup: isolationGroup ?? this.DEFAULT_ISOLATION_GROUP,
      privateMode: isPrivate
    });
    
    // 更新映射
    this.webContentsToTabId.set(view.webContents.id, tabId);
    this.indexToTabId.set(newIndex, tabId);

    // 如果是无痕模式，设置相关隐私选项
    if (isPrivate) {
      // 禁用持久化存储
      view.webContents.session.setPermissionRequestHandler((_, permission, callback) => {
        if (permission === 'storage-access' || permission === 'top-level-storage-access' || partition === 'unknown') {
          callback(false)
        }
        callback(true)
      });

      // // 禁用缓存
      // try {
      //   // 使用类型断言访问可能不在类型定义中的方法
      //   (view.webContents.session as any).setCacheEnabled(false);
      // } catch (error) {
      //   console.error('禁用缓存失败:', error);
      //   // 备选方案：使用clearCache周期性清除缓存
      //   view.webContents.session.clearCache();
      // }
    }

    // 将视图添加到窗口
    this.window.contentView.addChildView(view);
    this.tabs.push(view);
    this.currentTabIndex = this.tabs.length - 1;

    // 设置标签页事件监听
    this.setupTabEvents(view, tabId);

    // 加载页面并设置初始尺寸
    this.updateViewBounds(view);

    // 处理URL
    this.loadURL(view.webContents, url);

    // 隐藏其他标签页
    this.tabs.forEach((v, i) => {
      if (i !== this.currentTabIndex) {
        v.setVisible(false);
      }
    });

    // 确保当前标签页可见
    view.setVisible(true);
    
    this.emitTabChange(tabId);
    
    // 创建标签页成功
    logger.info('TabManager', LogCategory.TAB, `创建标签页成功, ID: ${tabId}, URL: ${url}`);
    
    return tabId;
  }

  // 处理URL加载
  private loadURL(webContents: Electron.WebContents, url: string) {
    try {
      // 处理内部页面
      if (url.startsWith('chrome://')) {
        const page = url.replace('chrome://', '');
        switch (page) {
          case 'history':
          case 'bookmarks':
          case 'downloads':
          case 'settings':
          case 'extensions':
            // 这里实际应用中应该加载相应的内部页面
            webContents.loadFile(`./internal/${page}.html`);
            break;
          case 'newtab':
            webContents.loadFile('./internal/newtab.html');
            break;
          default:
            webContents.loadURL('about:blank');
            break;
        }
        return;
      }

      // 处理about:页面
      if (url === 'about:blank' || url === 'about:newtab') {
        webContents.loadURL('about:blank');
        return;
      }

      // 如果URL没有协议且不是特殊URL，自动添加https协议
      let loadUrl = url;
      if (!url.startsWith('http://') && !url.startsWith('https://') &&
          !url.startsWith('file://') && !url.startsWith('about:')) {
        // 检查URL是否包含域名分隔符
        if (url.includes('.')) {
          loadUrl = `https://${url}`;
        } else {
          // 假设是搜索查询，重定向到搜索引擎
          const encodedQuery = encodeURIComponent(url);
          loadUrl = `https://www.bing.com/search?q=${encodedQuery}`;
        }
      }

      webContents.loadURL(loadUrl);
    } catch (error) {
      logger.error('TabManager', LogCategory.TAB, '加载URL失败', error);
      webContents.loadURL('about:blank');
    }
  }

  // 设置标签页事件监听
  private setupTabEvents(view: WebContentsView, tabId: number) {
    const { webContents } = view;

    // 页面标题变更
    webContents.on('page-title-updated', (_, title) => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.title = title;
        this.emitTabChange(tabId);
      }
    });

    // 页面加载状态变更
    webContents.on('did-start-loading', () => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.isLoading = true;
        // 开始加载时重置错误状态
        tabInfo.hasError = false;
        tabInfo.errorDescription = undefined;
        this.emitTabChange(tabId);
      }
    });

    webContents.on('did-stop-loading', () => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.isLoading = false;
        tabInfo.canGoBack = webContents.canGoBack();
        tabInfo.canGoForward = webContents.canGoForward();
        this.emitTabChange(tabId);
      }
    });

    // 页面导航完成
    webContents.on('did-navigate', (_, url) => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.url = url;
        tabInfo.canGoBack = webContents.canGoBack();
        tabInfo.canGoForward = webContents.canGoForward();
        this.emitTabChange(tabId);
      }
    });

    // 页面图标更新
    webContents.on('page-favicon-updated', (_, favicons) => {
      if (favicons.length > 0) {
        const tabInfo = this.tabInfos.get(tabId);
        if (tabInfo) {
          tabInfo.favicon = favicons[0];
          this.emitTabChange(tabId);
        }
      }
    });

    // 监听导航状态变化
    webContents.on('did-navigate-in-page', () => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.canGoBack = webContents.canGoBack();
        tabInfo.canGoForward = webContents.canGoForward();
        this.emitTabChange(tabId);
      }
    });

    // 处理页面加载失败
    webContents.on('did-fail-load', (_, errorCode, errorDescription) => {
      // 忽略取消导航的错误，因为这通常不是真正的错误
      if (errorCode === -3) return;

      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.isLoading = false;
        tabInfo.hasError = true;
        tabInfo.errorDescription = errorDescription;
        this.emitTabChange(tabId);
      }
    });

    // 处理渲染进程崩溃
    webContents.on('render-process-gone', (_, details) => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.isLoading = false;
        tabInfo.hasError = true;
        tabInfo.errorDescription = `页面崩溃 (${details.reason})`;
        this.emitTabChange(tabId);
      }
    });

    // 处理未响应
    webContents.on('unresponsive', () => {
      const tabInfo = this.tabInfos.get(tabId);
      if (tabInfo) {
        tabInfo.isLoading = false;
        tabInfo.hasError = true;
        tabInfo.errorDescription = '页面无响应';
        this.emitTabChange(tabId);
      }
    });

    // 新窗口请求处理（使用正确的类型）
    webContents.on('new-window' as any, (event: Electron.Event, url: string, _: string, disposition: string) => {
      event.preventDefault();

      // 向渲染进程发送新窗口请求
      this.window.webContents.send('new-window-request', {
        url,
        disposition,
        options: {
          isolationGroup: this.tabInfos.get(tabId)?.isolationGroup,
          privateMode: this.tabInfos.get(tabId)?.privateMode
        }
      });
    });

    // 以上同源策略的方式处理弹出窗口
    webContents.setWindowOpenHandler(({ url, disposition }) => {
      this.window.webContents.send('new-window-request', {
        url,
        disposition,
        options: {
          isolationGroup: this.tabInfos.get(tabId)?.isolationGroup,
          privateMode: this.tabInfos.get(tabId)?.privateMode
        }
      });

      return { action: 'deny' };
    });
  }

  // 通知标签页状态变化
  private emitTabChange(tabId: number) {
    const tabInfo = this.tabInfos.get(tabId);
    if (tabInfo) {
      this.window.webContents.send('tab-updated', tabInfo);
    }
  }

  // 更新标签页视图大小
  private updateViewBounds(view: WebContentsView) {
    if (this.window.isDestroyed()) return;

    // 获取内容区域大小
    const bounds = this.window.getContentBounds();

    // 估算标题栏和导航栏的高度
    const headerHeight = 80; // 标题栏+导航栏的高度，根据实际UI调整

    // 设置内容区域大小
    view.setBounds({
      x: 0,
      y: headerHeight,
      width: bounds.width,
      height: bounds.height - headerHeight
    });
  }

  // 获取标签页信息
  getTabInfo(index: number): TabInfo | undefined {
    if (index >= 0 && index < this.tabs.length) {
      const tabId = this.getTabIdByIndex(index);
      return tabId !== -1 ? this.tabInfos.get(tabId) : undefined;
    }
    return undefined;
  }

  // 根据索引获取标签ID
  private getTabIdByIndex(index: number): number {
    if (index < 0 || index >= this.tabs.length) {
      logger.warn('TabManager', LogCategory.TAB, `无效的标签索引: ${index}, 范围应为 0-${this.tabs.length - 1}`);
      return -1;
    }
    
    // 使用索引映射
    const tabId = this.indexToTabId.get(index);
    if (tabId !== undefined) {
      return tabId;
    }
    
    logger.warn('TabManager', LogCategory.TAB, `未找到索引 ${index} 对应的标签ID`);
    return -1;
  }

  // 根据标签ID获取视图
  private getViewByTabId(tabId: number): WebContentsView | undefined {
    const view = this.tabs.find((_, index) => this.getTabIdByIndex(index) === tabId);
    if (!view) {
      logger.warn('TabManager', LogCategory.TAB, `未找到ID为 ${tabId} 的标签视图`);
    }
    return view;
  }

  // 为视图查找tabId
  private getTabIdForView(view: WebContentsView): number {
    if (!view.webContents) {
      logger.error('TabManager', LogCategory.TAB, '视图没有关联的WebContents');
      return -1;
    }

    const webContentsId = view.webContents.id;
    const tabId = this.webContentsToTabId.get(webContentsId);
    
    if (tabId === undefined) {
      logger.warn('TabManager', LogCategory.TAB, `未找到WebContents ID ${webContentsId} 对应的标签ID`);
      return -1;
    }
    
    return tabId;
  }

  // 切换到指定标签页
  switchTab(index: number) {
    if (index >= 0 && index < this.tabs.length) {
      // 隐藏所有标签页
      this.tabs.forEach(view => view.setVisible(false));

      // 显示目标标签页
      const target = this.tabs[index];
      target.setVisible(true);

      // 检查是否为休眠标签，如果是则恢复
      const tabId = this.getTabIdByIndex(index);
      if (tabId !== -1) {
        const tabInfo = this.tabInfos.get(tabId);
        if (tabInfo && tabInfo.isHibernated && tabInfo.resumeURL) {
          // 恢复标签内容
          tabInfo.isHibernated = false;
          target.webContents.loadURL(tabInfo.resumeURL);
        }
      }

      this.currentTabIndex = index;

      // 通知渲染进程标签切换
      if (tabId !== -1) {
        this.window.webContents.send('tab-activated', tabId);
      }
    }
  }

  // 关闭指定标签页
  closeTab(index: number) {
    if (index < 0 || index >= this.tabs.length) {
      logger.warn('TabManager', LogCategory.TAB, `尝试关闭无效索引的标签页: ${index}`);
      return false;
    }

    const tabId = this.getTabIdByIndex(index);
    const [closed] = this.tabs.splice(index, 1);
    
    logger.info('TabManager', LogCategory.TAB, `关闭标签页, 索引: ${index}, ID: ${tabId}`);

    // 更新映射
    this.webContentsToTabId.delete(closed.webContents.id);
    this.indexToTabId.delete(index);
    
    // 更新所有大于当前索引的映射
    for (let i = index; i < this.tabs.length; i++) {
      const oldTabId = this.indexToTabId.get(i + 1);
      if (oldTabId !== undefined) {
        this.indexToTabId.set(i, oldTabId);
        this.indexToTabId.delete(i + 1);
      }
    }

    // 正确销毁资源
    this.window.contentView.removeChildView(closed);

    // 如果是无痕模式，清除所有数据
    const tabInfo = tabId !== -1 ? this.tabInfos.get(tabId) : undefined;
    if (tabInfo?.privateMode) {
      try {
        // 清除所有会话数据
        closed.webContents.session.clearStorageData({
          storages: [
            'cookies',
            'filesystem',
            'indexdb',
            'localstorage',
            'shadercache',
            'websql',
            'serviceworkers',
            'cachestorage',
          ]
        });
        // 清除HTTP缓存
        closed.webContents.session.clearCache();
        // 清除主机解析缓存
        closed.webContents.session.clearHostResolverCache();
      } catch (e) {
        logger.error('TabManager', LogCategory.TAB, '清除无痕标签数据失败', e);
      }
    }

    // 关闭webContents以释放资源
    closed.webContents.close();

    // 从映射中移除
    if (tabId !== -1) {
      this.tabInfos.delete(tabId);
    }

    // 更新当前标签索引
    if (this.currentTabIndex >= index) {
      this.currentTabIndex = Math.max(0, this.currentTabIndex - 1);
    }

    // 如果还有标签，切换到新的当前标签
    if (this.tabs.length > 0) {
      this.switchTab(this.currentTabIndex);
    }

    // 通知渲染进程标签已关闭
    this.window.webContents.send('tab-closed', tabId);

    return true;
  }

  // 刷新当前标签页
  refreshCurrentTab() {
    if (this.currentTabIndex >= 0 && this.currentTabIndex < this.tabs.length) {
      const tab = this.tabs[this.currentTabIndex];
      const tabId = this.getTabIdByIndex(this.currentTabIndex);
      const tabInfo = tabId !== -1 ? this.tabInfos.get(tabId) : undefined;

      if (tabInfo) {
        tabInfo.isLoading = true;
        this.emitTabChange(tabId);
        tab.webContents.reload();
      }
    }
  }

  // 导航到指定URL
  navigateTo(index: number, url: string) {
    if (index >= 0 && index < this.tabs.length) {
      this.loadURL(this.tabs[index].webContents, url);
      return true;
    }
    return false;
  }

  // 前进
  goForward(index: number) {
    if (index >= 0 && index < this.tabs.length) {
      const webContents = this.tabs[index].webContents;
      if (webContents.canGoForward()) {
        webContents.goForward();
        return true;
      }
    }
    return false;
  }

  // 后退
  goBack(index: number) {
    if (index >= 0 && index < this.tabs.length) {
      const webContents = this.tabs[index].webContents;
      if (webContents.canGoBack()) {
        webContents.goBack();
        return true;
      }
    }
    return false;
  }

  // 销毁所有标签页并释放资源
  destroy() {
    logger.info('TabManager', LogCategory.SYSTEM, `销毁标签管理器, 标签数量: ${this.tabs.length}`);
    
    for (const view of this.tabs) {
      try {
        // 从窗口中移除视图
        if (!this.window.isDestroyed()) {
          this.window.contentView.removeChildView(view);
        }

        const tabId = this.getTabIdForView(view);
        const tabInfo = tabId !== -1 ? this.tabInfos.get(tabId) : undefined;

        // 如果是无痕模式或指定了清除数据，则清除所有会话数据
        if (tabInfo?.privateMode) {
          try {
            view.webContents.session.clearStorageData();
            view.webContents.session.clearCache();
            view.webContents.session.clearHostResolverCache();
          } catch (e) {
            logger.error('TabManager', LogCategory.SYSTEM, '销毁时清除无痕标签数据失败', e);
          }
        }

        // 关闭webContents以释放资源
        if (!view.webContents.isDestroyed()) {
          view.webContents.close();
        }
      } catch (e) {
        logger.error('TabManager', LogCategory.TAB, '销毁标签失败', e);
      }
    }

    // 清空数组和映射
    this.tabs = [];
    this.tabInfos.clear();
    this.webContentsToTabId.clear();
    this.indexToTabId.clear();
    this.sessionPartitions.clear();
    this.currentTabIndex = -1;
    
    logger.info('TabManager', LogCategory.SYSTEM, '标签管理器销毁完成');
  }

  // 休眠标签页以节省资源
  async hibernateTab(index: number): Promise<boolean> {
    try {
      if (index < 0 || index >= this.tabs.length || index === this.currentTabIndex) {
        return false;
      }

      const tabId = this.getTabIdByIndex(index);
      if (tabId === -1) return false;

      const tabInfo = this.tabInfos.get(tabId);
      const view = this.tabs[index];

      if (!tabInfo || !view || tabInfo.isHibernated) {
        return false;
      }

      // 保存当前URL以便稍后恢复
      tabInfo.resumeURL = tabInfo.url;
      tabInfo.isHibernated = true;

      // 加载空白页来释放资源
      view.webContents.loadURL('about:blank');

      // 通知状态变化
      this.emitTabChange(tabId);

      // 当窗口被激活时，如果标签仍然存在，自动恢复它
      const self = this;
      self.window.on('focus', function checkActivation() {
        const stillExists = self.tabs.includes(view) && !view.webContents.isDestroyed();

        if (!stillExists) {
          // 标签已被关闭，移除监听器
          self.window.removeListener('focus', checkActivation);
        } else if (tabInfo.isHibernated && self.currentTabIndex === index) {
          // 标签仍在休眠且是当前活动标签，恢复它
          tabInfo.isHibernated = false;
          if (tabInfo.resumeURL) {
            view.webContents.loadURL(tabInfo.resumeURL);
          }
          self.emitTabChange(tabId);
        }
      });

      return true;
    } catch (e) {
      logger.error('TabManager', LogCategory.TAB, '休眠标签失败', e);
      return false;
    }
  }
}
